require "Common/define"
require "Logic/Config"
require "Common/functions"
---@class FuncOpenManager
FuncOpenManager = {};
local this = FuncOpenManager;

local tableGo = {};
local viewToNames = {};
local goId2LockId = {};
local funcConfig;
local configKeys
local configValues = {}
this.serverLock = {};--服务端控制解锁

function FuncOpenManager.init()
    if funcConfig == nil then
        funcConfig = G.dataTable["t_functionswitch"];
    end
    CloseEvent(Config.EventType.Fresh_Level, this.refreshStatus);
    CloseEvent(Config.EventType.VIPInfoUpdate, this.refreshStatus);
    ListenEvent(Config.EventType.Fresh_Level, this.refreshStatus);
    ListenEvent(Config.EventType.VIPInfoUpdate, this.refreshStatus);
end

function FuncOpenManager.GetLockTip(id)
    local singleConfig = funcConfig[tostring(id)];
    if singleConfig then
        return getLanguage(singleConfig.f_LockTips)
    end
    return ""
end
function FuncOpenManager.ShowView(id, str, obj)
    --若有obj则显示框 否则飘字
    if obj then
        showUI(PanelNames.UIFuncOpenView, id, str, obj)
    else
        UISysTips.AddMsg(str);
    end
end
function FuncOpenManager.ShowLockTip(id, singleConfig, index, obj, param)
    --if type(index) == "number" then
    --单个锁定
    --    if index == 1 then
    --        this.ShowView(id, string.format(getLanguage("FunctionTipsLevel"), singleConfig.f_UnlockLevel), obj)
    --    elseif index == 2 then
    --        local config = G.dataTable["t_stage"][tostring(singleConfig.f_UnlockStage)];
    --        if config ~= nil then
    --            local str = config.f_ChapterId .. "-" .. config.f_StageNum;
    --            this.ShowView(id, string.format(getLanguage("FunctionTipsStage"), str), obj)
    --        else
    --            printError("t_stage 缺少解锁关卡 ", singleConfig.f_UnlockStage)
    --        end
    --    elseif index == 3 then
    --        if logicMgr.GuildManager.getUnionLv() <= 0 then
    --            this.ShowView(id, string.format(getLanguage("SourceTips5"), singleConfig.f_UnlockGuildRank), obj)
    --        else
    --            this.ShowView(id, string.format(getLanguage("SourceTips6"), singleConfig.f_UnlockGuildRank), obj)
    --        end
    --    elseif index == 4 then
    --        this.ShowView(id, string.format(getLanguage("FunctionTipsVip"), singleConfig.f_UnlockVipRank), obj)
    --    elseif index == 5 then
    --        this.ShowView(id, string.format(getLanguage("FunctionTipsRank"), EnumConst.StarType[singleConfig.f_UnlockHeroRank / 10]), obj)
    --    elseif index == 6 then
    --        local str = math.ceil(param / (3600 * 24)) .. getLanguage("ActivityListTaohuaTips8") .. getLanguage("FunctionNameUnlockTime");
    --        this.ShowView(id, str, obj)
    --    end
    --elseif type(index) == "table" then
    --多个锁定
    local sort = { 6, 2 };
    if type(param) == "table" and param.isDecTip then
        UISysTips.AddMsg(getLanguage(singleConfig.f_FunctionOpenDes));
    elseif singleConfig.f_LockTips ~= nil and singleConfig.f_LockTips ~= "" then
        this.ShowView(id, getLanguage(singleConfig.f_LockTips), obj)
    else
        local str = "";
        local connectCount = table.getn(index) - 1;
        for i, v in ipairs(index) do
            if v == 1 then
                str = str .. string.format(getLanguage("FunctionTipsLevel"), singleConfig.f_UnlockLevel);
            elseif v == 2 then
                local config = G.dataTable["t_stage"][tostring(singleConfig.f_UnlockStage)];
                if config ~= nil then
                    local stageStr = config.f_ChapterId .. "-" .. config.f_StageNum;
                    str = str .. string.format(getLanguage("FunctionTipsStage"), stageStr)
                else
                    printError("t_stage 缺少解锁关卡 ", singleConfig.f_UnlockStage)
                end
            elseif v == 3 then
                if logicMgr.GuildManager.getUnionLv() <= 0 then
                    str = str .. string.format(getLanguage("SourceTips5"), singleConfig.f_UnlockGuildRank)
                else
                    str = str .. string.format(getLanguage("SourceTips6"), singleConfig.f_UnlockGuildRank)
                end
            elseif v == 4 then
                str = str .. string.format(getLanguage("FunctionTipsVip"), singleConfig.f_UnlockVipRank)
            elseif v == 5 then
                str = str .. string.format(getLanguage("FunctionTipsRank"), EnumConst.StarType[singleConfig.f_UnlockHeroRank / 10])
            elseif v == 6 then
                str = str .. math.ceil(param.time / (3600 * 24)) .. getLanguage("FunctionSwitchUnlockTips3");
            elseif v == 7 then
                str = str..getLanguage("FunctionUnlockFirstChargeTips");
            end
            if connectCount >= 1 then
                str = str .. getLanguage("FunctionSwitchUnlockTips1");
                connectCount = connectCount - 1;
            end
        end
        local string = str .. getLanguage("FunctionSwitchUnlockTips2");
        this.ShowView(id, string, obj);
    end
    --end

end

local lock_cache = {}
--param{解锁参数
--heroId 英雄的modelId 如果要启用f_UnlockVipRank字段判断必须要传英雄唯一Id
-- isDecTip 是否使用f_FunctionOpenDes字段来描述
--}

FuncOpenManager.unlock_check1 = function(config)
    return logicMgr.HeroManager.GetRoleLevel() >= config.f_UnlockLevel
end

FuncOpenManager.unlock_check2 = function(config)
    if (config.f_FunctionId == Config.FuncOpenType.BattleSpeed or config.f_FunctionId == Config.FuncOpenType.BattleSpeed_5) then
        return (logicMgr.MapManager.GetBattleBeforeMapId() or 0) >= config.f_UnlockStage
    end
    return logicMgr.MapManager.getMapId() >= config.f_UnlockStage
end

FuncOpenManager.unlock_check3 = function(config)
    return logicMgr.GuildManager.getUnionLv() >= config.f_UnlockGuildRank
end

FuncOpenManager.unlock_check4 = function(config)
    return logicMgr.VipManager.getVipLevel() >= config.f_UnlockVipRank
end

FuncOpenManager.unlock_check5 = function(config, hid)
    local heroData = HeroManager.getHeroDatabyPartnerId(hid,true);
    if heroData then
        return heroData.star >= config.f_UnlockHeroRank
    end
    return false
end

FuncOpenManager.unlock_check6 = function(config)
    local serverOpenTime = config.f_UnlockTime or 0
    if serverOpenTime ~= 0 then
        local ot = tonumber(tostring((logicMgr.LoginManager.GetServerOpenTime() / 1000)))
        local t = tonumber(os.date("!%H", ot+8*3600))

        local updateTime = G.dataTable["t_global"][tostring(35)].f_int_value;
        local openTime = 0
        if t * 3600 >= updateTime then
            openTime = logicMgr.ActiveManager.getDataUpateTimeGMT8(ot) + serverOpenTime * 3600 * 24 - HelperFunc.GetServerTime();
        else
            openTime = logicMgr.ActiveManager.getDataUpateTimeGMT8(ot + 3600 * 24) + serverOpenTime * 3600 * 24 - HelperFunc.GetServerTime();
        end
        if openTime > 0 then
            return false, openTime
        end
    end
    return true;
end

FuncOpenManager.unlock_check7 = function(config)
    if logicMgr.CostManager.getPlayerRechargeNum() > 0  then
        return true;
    end
    return false;
end

function FuncOpenManager.isOpen(id, showTip, obj, param)
    local singleConfig = funcConfig[tostring(id)];
    if singleConfig == nil then
        return true;
    end

    --[[if lock_cache[id] and lock_cache[id].unlock then
        return true
    end--]]

    if singleConfig.f_Mask == 1 or this.serverLock[id] then
        if showTip then
            UISysTips.AddMsg(getLanguage("FunctionTipsLocked"));
        end
        return false;
    end

    local unlock = true

    local _flag, openTime = this.unlock_check6(singleConfig);
    if not _flag then
        if param == nil then
            param = {};
        end
        param.time = openTime

        if showTip then
            this.ShowLockTip(id, singleConfig, {6}, obj, param);
        end
        return _flag, openTime;
    end

    if singleConfig.f_AndRelation ~= "" then
        local index = {}
        for k,v in pairs(singleConfig.f_AndRelation) do
            if v == 5 then
                if type(param) == "table" and param.heroId then
                    unlock = FuncOpenManager["unlock_check" .. v](singleConfig, param.heroId)
                end
            else
                unlock = FuncOpenManager["unlock_check" .. v](singleConfig)
            end

            if not unlock then
                table.insert(index, v)
            end
        end

        if #index > 0 then
            if showTip then
                this.ShowLockTip(id, singleConfig, index, obj, param);
            end
            return false
        end
    elseif singleConfig.f_OrRelation ~= "" then
        local b = false
        local index = {}
        for k,v in pairs(singleConfig.f_OrRelation) do
            if v == 5 then
                if type(param) == "table" and param.heroId then
                    b = FuncOpenManager["unlock_check" .. v](singleConfig, param.heroId)
                end
            else
                b = FuncOpenManager["unlock_check" .. v](singleConfig)
            end

            if b then
                break
            else
                if #index == 0 then
                    table.insert(index, v)
                end
            end
        end

        if not b then
             if showTip then
                this.ShowLockTip(id, singleConfig, index, obj, param);
            end
            return b
        end
    end

    lock_cache[id] = {unlock = true}

    return true
end
--param{解锁参数
--heroId 英雄的modelId 如果要启用f_UnlockVipRank字段判断必须要传英雄modelId
-- isDecTip 是否使用f_FunctionOpenDes字段来描述
--}
function FuncOpenManager.addStatusCtr(viewName, id, name, go, param)
    if HelperFunc.IsNull(go) then
        return
    end
    if viewToNames[viewName] == nil then
        viewToNames[viewName] = {};
    end
    table.insert(viewToNames[viewName], { name = name, id = id });
    if tableGo == nil then
        tableGo = {};
    end
    if id ~= nil and id ~= "" then
        if tableGo[id] == nil then
            tableGo[id] = {};
        end

        goId2LockId[go.id] = id;
        table.insert(tableGo[id], { go = go, name = name, param = param });
        local typeId, grayId, lockId, hideId, showId = this.checkStatus(id, param);
        this.setGameObjectStatus(typeId, grayId, lockId, hideId, go, showId);
    end
end

function FuncOpenManager.removeStatusCtr(viewName)
    if viewToNames[viewName] == nil then
        return ;
    end
    for i, v in pairs(viewToNames[viewName]) do
        if tableGo[v.id] ~= nil then
            for i = #tableGo[v.id], 1, -1 do
                if tableGo[v.id][i].name == v.name then
                    table.remove(tableGo[v.id], i);
                    --table.remove(tableGo[v.id][i]);

                    --local tb = {};
                    --local lock = tableGo[v.id][i].go:GetController("lock");
                    --if lock then
                    --    lock.selectedIndex = 1;
                    --end
                    --this.getComponent(go,"Image",tb);
                    --for i = 1, #tb do
                    --   setGray(tb[i],false);
                    --end
                end
            end
        end
    end
end

function FuncOpenManager.refreshStatus()
    for key, value in pairs(tableGo) do
        for i = 1, #value do
            local typeId, grayId, lockId, hideId, showId = this.checkStatus(key, value[i]);
            this.setGameObjectStatus(typeId, grayId, lockId, hideId, value[i].go, showId);
        end
    end
end

function FuncOpenManager.jump(id, showTip)
    if this.isOpen(id, showTip) then
        local singleConfig = funcConfig[tostring(id)];
        if not singleConfig then
            logError("找不到t_functionswitch id: " .. id)
            return false
        end
        local jump = singleConfig.f_Jump
        if jump ~= nil and jump ~= "" then
            if jump == "UIBattle" then
                UIBottom.onSetBattle();
                if tonumber(singleConfig.f_JumpCo) == 1 then
                    UIBattle.onClickBoss2();
                elseif tonumber(singleConfig.f_JumpCo) == 2 then
                    UIBattle.onClickQuick();
                elseif tonumber(singleConfig.f_JumpCo) == 3 then
                    UIBattle.onAutoHardMode();
                end
            elseif jump == "UIDraw" then
                UIBottom.enterDrawto(singleConfig.f_JumpCo)
            elseif jump == "UIAdventureMain" then
                UIBottom.enterAdventure()
            elseif jump == "UICharactorMain" then
                UIBottom.enterPlayer()
            elseif jump == "UICity" then
                UIBottom.enterTown()
            elseif jump == "UILongJourneySelect" then
                --showUI(PanelNames.UIAdventureMain)
                logicMgr.UIShowManager.ShowExpeditionViewImmediate()
            elseif jump == "UISoloBattle" then
                UIBottom.enterAdventure();
                logicMgr.RealManWarManager.OpenSoloBattle(1);
            elseif jump == "UILongJourneyHell" then
                logicMgr.LongJourneyHellManager.getLongJourneyHellServerData()
            else
                if isOpenUI(singleConfig.f_Jump) then
                    if singleConfig.f_JumpCo ~= nil and singleConfig.f_JumpCo ~= "" then
                        local ui_jump = CtrlManager.GetCtrl(singleConfig.f_Jump)
                        if ui_jump ~= nil and ui_jump.OnJump ~= nil then
                            ui_jump:OnJump(singleConfig.f_JumpCo)
                        end
                    end
                    return false;
                end

                if singleConfig.f_JumpCo ~= "" then
                    if singleConfig.f_FristFunc == 0 then
                        showUI(singleConfig.f_Jump, singleConfig.f_JumpCo);
                    else
                        showUI(singleConfig.f_Jump, nil, singleConfig.f_JumpCo);
                    end
                else
                    showUI(singleConfig.f_Jump);
                end
            end
            return true
        end
    end
    return false
end

function FuncOpenManager.checkStatus(id, param)
    local singleConfig = funcConfig[tostring(id)];
    local typeId = 0; -- 0开放 1未开放 2屏蔽
    local grayId = 0; -- 0 置灰 1 隐藏
    local lockId = 0; -- 0或不填上锁 1隐藏
    local hideId = 0; -- 0或不填显示 1隐藏
    local showId = 0  -- 不填直接显示 填按开启显示和隐藏
    if singleConfig ~= nil then
        --回放强制打开跳过 （实在没办法只能这样写）
        if logicMgr.BattlePlaybackManager.GetIsRecord() == 1 and
                (id == Config.FuncOpenType.MainBattleSkip or
                        id == Config.FuncOpenType.ArenaBattleSkip or
                        id == Config.FuncOpenType.TowerBattleSkip or
                        id == Config.FuncOpenType.MythicBattleSkip or
                        id == Config.FuncOpenType.ExpeditionBattleSkip or
                        id == Config.FuncOpenType.TrialsSkip)
        then
            grayId = 1;
        else
            if singleConfig.f_Mask == 1 then
                typeId = 2;
            else
                --if G.serverData["roleInfo"] then
                --local curLevel = logicMgr.HeroManager.GetRoleLevel()
                --local mapId = logicMgr.MapManager.GetBattleBeforeMapId();
                --防止打到解锁战斗加速关卡的关卡提前开放战斗加速
                --if singleConfig.f_FunctionId == Config.FuncOpenType.BattleSpeed or singleConfig.f_FunctionId == Config.FuncOpenType.BattleSpeed_5 then
                --    if mapId == singleConfig.f_UnlockStage then
                --        --mapId = logicMgr.MapManager.GetBattleBeforeMapId();
                --    end
                --end
                --if curLevel < singleConfig.f_UnlockLevel or mapId < singleConfig.f_UnlockStage then
                if not FuncOpenManager.isOpen(id, nil, nil, param) then
                    typeId = 1;
                    grayId = singleConfig.f_LockShade == nil and 0 or singleConfig.f_LockShade;
                    lockId = singleConfig.f_LockShow == nil and 0 or singleConfig.f_LockShow;
                    hideId = singleConfig.f_Mask1 == nil and 0 or singleConfig.f_Mask1;
                end
                --end 
            end
        end
        showId = FuncOpenManager.isShow(id)
    end
    return typeId, grayId, lockId, hideId, showId;
end
function FuncOpenManager.isShow(id)
    local singleConfig = funcConfig[tostring(id)];
    -- body
    local f_ShowUnlockStage = singleConfig.f_ShowUnlockStage
    if logicMgr.MapManager.GetBattleBeforeMapId() and f_ShowUnlockStage then
        if logicMgr.MapManager.GetBattleBeforeMapId() < f_ShowUnlockStage then
            return 1
        end
    end

    return 0
end
---@param go FairyGUI.GComponent
function FuncOpenManager.setGameObjectStatus(typeId, grayId, lockId, hideId, go, showId)
    if HelperFunc.IsNull(go) then
        return
    end
    if HelperFunc.IsNull(go)
            or HelperFunc.IsNull(go.displayObject)
            or HelperFunc.IsNull(go.displayObject.gameObject) then
        return ;
    end
    local item = go:GetChild("lock");
    if typeId == 0 then
        go.visible = true
        go.grayed = false;
        if item ~= nil then
            local show = item:GetController("show")
            if show then
                show.selectedIndex = 0;
            end
        end
    elseif typeId == 1 then

        if hideId == 0 then
            go.visible = true;
            if showId == 0 then
                go.visible = true
            else
                go.visible = false
            end
        else
            go.visible = false;
        end

        if grayId == 0 then
            go.grayed = true;
        else
            go.grayed = false;
        end

        if lockId == 0 then
            local name, package = getUIName(PanelNames.lock);
            if not item then
                item = newGComponent(name, package);
                item.name = "lock"
                --item:GetChild("icon").url = "ui://ICONAtlas/img_lock";
                go:AddChild(item);
                item:SetPosition(go.width / 2, go.height / 2, Vector3.zero.z);
                item:SetScale(1, 1);
                item:GetController("show").selectedIndex = 1;
            else
                item:GetController("show").selectedIndex = 1;
            end
        else
            local item = go:GetChild("lock");
            if item ~= nil then
                item:GetController("show").selectedIndex = 0;
            end
        end
        local redDot = go:GetChild("UIRedDots");
        if redDot then
            redDot:GetController("c1").selectedIndex = 0;
        end
    else
        go.visible = false
    end

end

function FuncOpenManager.checkItemState(go)
    if goId2LockId[go.id] == nil then
        return true;
    end
    local typeId, grayId, lockId, showId = this.checkStatus(goId2LockId[go.id]);
    if typeId == 1 then
        return false;
    end
    return true;
end

---@param uiMainReward GComponent
---@param fId number
function FuncOpenManager.refreshMainReward(uiMainReward,fId,list,rewardJsonStr)
    if uiMainReward then
        local hasReward = false
        if fId then
            fId = tostring(fId)
            local rewardJson
            if rewardJsonStr then
                rewardJson = rewardJsonStr
            else
                local functionSwitch = G.dataTable["t_functionswitch"]
                local systemData = functionSwitch[fId]
                if systemData then
                    rewardJson = systemData.f_FunctionRroduction
                end

            end

            if rewardJson and rewardJson~="" then
                local rewardData = decodeJsonStrToTabel(rewardJson)
                if rewardData and #rewardData > 0 then
                    hasReward = true
                    local listReward
                    if list then
                        listReward = list
                    else
                        listReward = uiMainReward:GetChild("list")
                    end

                    if listReward then
                        listReward:RemoveChildrenToPool()
                        local itemCtrl = CtrlManager.GetCtrl(PanelNames.Item)
                        for i, _id in ipairs(rewardData) do
                            local item = listReward:AddItemFromPool()
                            local itemData = {}
                            itemData["itemModelId"] = _id
                            itemCtrl.initData(item, itemData);
                        end
                    end
                end
            end
        end
        uiMainReward.visible = hasReward
    end
end

--function FuncOpenManager.getComponent(go, comName, list)
--    local com = go.transform:GetComponent(comName);
--    if com ~= nil then
--        table.insert(list, com);
--    end
--    local count = go.transform.childCount;
--    for i = 1, count do
--        this.getComponent(go.transform:GetChild(i - 1), comName, list);
--    end
--end

return FuncOpenManager